
from ftplib import FTP
import re,os
# from unrar import rarfile
import re,pymysql,datetime,time,paramiko,subprocess
import shutil# 高级文件操作模块
from unrar import rarfile


class Linux(object):
    # 通过IP, 用户名，密码，超时时间初始化一个远程Linux主机
    def __init__(self, ip, username, password, timeout=30):
        self.ip = ip
        self.username = username
        self.password = password
        self.timeout = timeout
        # transport和chanel
        self.t = ''
        self.chan = ''
        # 链接失败的重试次数
        self.try_times = 3

    # 调用该方法连接远程主机
    def connect(self):
         pass

    # 断开连接
    def close(self):
        pass

    # 发送要执行的命令
    def send(self, cmd):
        pass

    # get单个文件
    def sftp_get(self, remotefile, localfile):
        t = paramiko.Transport(sock=(self.ip, 22))
        t.connect(username=self.username, password=self.password)
        sftp = paramiko.SFTPClient.from_transport(t)
        sftp.get(remotefile, localfile)
        t.close()

    # put单个文件
    def sftp_put(self, localfile, remotefile):
        t = paramiko.Transport(sock=(self.ip, 22))
        t.connect(username=self.username, password=self.password)
        sftp = paramiko.SFTPClient.from_transport(t)
        sftp.put(localfile, remotefile)
        t.close()

def integrated_package_download(g_product,output,g_version):
    """
    下载集成压缩包的方法
    :param g_product: 所属产品名字
    :param output: 修改单输出程序
    :param g_gersion: 集成包版本
    :return:
    """
    username = 'SecuUFT2.0-autotest' # 用户名
    password = '6odUdIf8'  # 密码
    ip = '192.168.102.242'  # ip地址
    port = 5212   # 端口号
    ftp = FTP() # 设置一个FTP变量
    ftp.set_debuglevel(2) # 打开调试级别2显示详细信息
    ftp.connect(ip,port) # 建立ftp连接
    ftp.login(username,password) # 登录账号密码
    remark1 = "连接ftp成功"
    to_path = '/home/dar/uft_download/' # 将集成包下载至这个文件夹
    integrated_package_path = output # 修改单的文件夹
    integrated_package_version = g_version # 修改单的版本

    # 执行cwd命令，进入目录
    ftp.cwd(integrated_package_path.encode('UTF-8').decode('latin-1'))
    bufsize = 1024  # 设置缓冲区大小
    ftp_list = ftp.nlst()  # 获取目录下的文件
    # 用正则匹配，找到对应的集成包。
    for filename in ftp_list:
        re_name = re.match('集成-M[0-9]+.*-{}'.format(integrated_package_version),filename.encode('latin_1').decode('UTF-8')) # 正则表达式匹配
        if re_name != None:
            print(filename.encode('latin-1').decode('utf-8'))
            file_handle = open(to_path + filename.encode("latin-1").decode("UTF-8"),'wb').write # 获取文件句柄
            ftp.retrbinary('RETR ' + filename,file_handle,bufsize) # 接受服务器文件并保存到本地
            remark2 = '下载{}成功'.format(filename.encode("latin-1").decode("UTF-8"))
            break
    ftp.set_debuglevel(0) # 关闭调试模式
    ftp.quit() # 退出ftp
    return to_path + filename.encode("latin-1").decode("UTF-8")


def clear_dir(): # 清空文件夹
    """
    # 清空文件夹方法
    # 判断是否有uft_download有则删除，没有的话就进行创建
    :return:
    """
    result = os.path.exists("/home/dar/uft_download") # 判断是否存在文件夹
    if result == True:
        # 存在则删除，之后创建文件夹
        shutil.rmtree('/home/dar/uft_download/')
        # 递归删除文件
        os.makedirs("/home/dar/uft_download")
    else:
        os.makedirs('/home/dar/uft_download')


def rar_file(path): # 将文件解压ls
    to_url = "/home/dar/uft_download/"
    file = rarfile.RarFile(path)  # 解压需要解压的文件
    rar_list = file.namelist() # 获取解压文件的列表
    for simple_file in rar_list:
        # 找到后缀为.so的文件并提取到特定的文件夹
        if re.match(".+\.so",simple_file) != None:
            file.extract(simple_file,to_url + 'uft_so')

def uft_upload():
    """
    将对应文件上传至对应服务器方法
    """
    ip_uft = [["10.20.37.104", "combine_mauft", "YSPtest@123"],
              ["10.20.37.105", "combine_mauft", "YSPtest@123"],
              ["10.20.38.103", "secumauft", "YSPtest@123"],
              ["10.20.38.104", "secumauft", "YSPtest@123"],
              ["10.20.38.102", "secumauft", "YSPtest@123"],
              ["10.20.37.106", "combine_mauft", "YSPtest@123"]
              ]
    # 写好IP地址，用户名，密码
    ip_no_uft = [
        ["10.20.38.102", "secumauft", "YSPtest@123"],
        ["10.20.37.106", "combine_mauft", "YSPtest@123"]
    ]
    # 若so中没有uft就不升级这些服务器
    # if ipaddr[1] == "combine_mauft":
    #     string1 = 'cd /home/combine_mauft/workspace/;stopall'
    #     stdin,stdout,stder = ssh.exec_command(string1)
    # else:
    #     string1 = 'cd /home/secumauft/workspace/;stopall'
    #     stdin, stdout, stder = ssh.exec_command(string1)
    # string = stdout.read().decode("GBK")
    # time.sleep(2)
    dir_lists = os.listdir('/home/dar/uft_download') # 获取文件夹下所有的文件名称
    for dir_list in dir_lists:
        if dir_list == "uft_so":
            # so文件会在uft_so下
            for ipaddr in ip_uft:
                # 进行遍历IP地址升级
                ssh = paramiko.SSHClient()  # 实例化SSH对象， 搭建120的ssh连接
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                ssh.connect(hostname=ipaddr[0], port=22, username=ipaddr[1], password=ipaddr[2])
                print("连接到{}服务器进行上传文件".format(ipaddr[0]),file = log_file)
                so_dir_dirlists = os.listdir("/home/dar/uft_download/uft_so")
                # 获取文件夹下的所有的so文件
                print("下边进行so的遍历",file = log_file)
                for so in so_dir_dirlists:
                    print("so名字:",so,file = log_file)
                    flag = 0 # 定义一个标志
                    try:
                        if  re.match(".*_uft_.*", so.encode('latin_1').decode('UTF-8')) and ipaddr in ip_no_uft:
                            continue
                        # 进行正则表达式匹配，若文件名称中好友_uft_而且IP地址符合，就暂停一次不进行升级
                        try:
                            if ipaddr[1] == "combine_mauft":
                                stdin, stdout, stderr = ssh.exec_command('strings /home/combine_mauft/appcom/{} | grep V3"\."'.format(so))
                            else:
                                stdin, stdout, stderr = ssh.exec_command('strings /home/secumauft/appcom/{} | grep V3"\."'.format(so))
                            # 进行版本判断
                            old_string = stdout.read().decode('GBK').strip() # 去除最后的换行符
                            print("old_string",old_string,file = log_file)
                            if old_string == "":
                            # 再次进行版本判断
                                if ipaddr[1] == "combine_mauft":
                                    stdin, stdout, stderr = ssh.exec_command(
                                        'strings /home/combine_mauft/appcom/{} | grep V8"\."'.format(so))
                                else:
                                    stdin, stdout, stderr = ssh.exec_command(
                                        'strings /home/secumauft/appcom/{} | grep V8"\."'.format(so))
                                old_string = stdout.read().decode('GBK').strip()
                            print("old_string",old_string,file = log_file)
                            old_so_list = old_string.split('.')
                        except:
                            try:
                                print("错误了",file = log_file)
                                if ipaddr[1] == "combine_mauft":
                                    stdin, stdout, stderr = ssh.exec_command(
                                        'strings /home/combine_mauft/appcom/{} | grep V3"\."'.format(so))
                                else:
                                    stdin, stdout, stderr = ssh.exec_command(
                                        'strings /home/secumauft/appcom/{} | grep V3"\."'.format(so))
                                old_string = stdout.read().decode('GBK').strip()
                                if old_string == "":
                                    if ipaddr[1] == "combine_mauft":
                                        stdin, stdout, stderr = ssh.exec_command(
                                            'strings /home/combine_mauft/appcom/{} | grep V8"\."'.format(so))
                                    else:
                                        stdin, stdout, stderr = ssh.exec_command(
                                            'strings /home/secumauft/appcom/{} | grep V8"\."'.format(so))
                                    old_string = stdout.read().decode('GBK').strip()
                                old_so_list = old_string.split('.')
                            except:
                                print('不会到这吧')
                                old_so_list = ['V3', '0', '0','0']
                        print(so,old_so_list,file = log_file)
                        if old_so_list == ['']:
                            flag = 1
                            # 此标志代表着服务器中没有此so文件，不需要进行备份
                            old_so_list = ['V3', '0', '0', '0']
                        try:
                            so_darout = subprocess.Popen('strings /home/dar/uft_download/uft_so/{} | grep V3"\."'.format(so),
                                                         shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                            # 进行新so文件的版本判断
                            sout,serr = so_darout.communicate()
                            new_string = sout.decode("GBK").strip()
                            if new_string == "":
                            # 再次进行判断
                                so_darout = subprocess.Popen(
                                    'strings /home/dar/uft_download/uft_so/{} | grep V8"\."'.format(so),
                                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                                sout, serr = so_darout.communicate()
                                new_string = sout.decode("GBK").strip()
                                print("new_string:",new_string,file = log_file)
                            new_list = new_string.split('.')
                        except:
                            so_darout = subprocess.Popen(
                                'strings /home/dar/uft_download/uft_so/{} | grep V3"\."'.format(so),
                                shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                            sout, serr = so_darout.communicate()
                            new_string = sout.decode("GBK").strip()
                            if new_string == "":
                                so_darout = subprocess.Popen(
                                    'strings /home/dar/uft_download/uft_so/{} | grep V8"\."'.format(so),
                                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                                sout, serr = so_darout.communicate()
                                new_string = sout.decode("GBK").strip()
                                print("new_string:",new_string,file = log_file)
                            new_list = new_string.split('.')
                        if new_list == ['']:
                            continue
                        # 如果文件夹为空，则暂停
                        print(ipaddr[1])
                        print("old_so__list:",old_so_list,"new_list:", new_list,file = log_file)
                        print("下边进行文件版本的判断，判断是否进行升级",file = log_file)
                        for i in range(1,4):
                            if int(new_list[i]) > int(old_so_list[i]):
                                print("进行so文件的升级：",file = log_file)
                                host = Linux(ipaddr[0],ipaddr[1],ipaddr[2])
                                localpath = r'/home/dar/uft_download/uft_so/' + so
                                if ipaddr[1]  == "combine_mauft":
                                    serverpath = r'/home/combine_mauft/appcom/' + so
                                else:
                                    serverpath = r'/home/secumauft/appcom/' + so
                                now = datetime.datetime.now().strftime("%Y-%m-%d/%H:%M:%S")
                                if flag == 0:
                                # 此时代表着服务器中有老文件，需要进行备份
                                    print("先将之前的文件备份：",file = log_file)
                                    if ipaddr[1] == "combine_mauft":
                                        stdin, stdout, stderr = ssh.exec_command(
                                            "cp -p /home/combine_mauft/appcom/{0} /home/combine_mauft/appcom/{1}".format(
                                                so, so + now))
                                    else:
                                        stdin, stdout, stderr = ssh.exec_command(
                                            "cp -p /home/secumauft/appcom/{0} /home/secumauft/appcom/{1}".format(so,
                                                                                                                 so + now))

                                host.sftp_put(localpath,serverpath)
                                print("升级完成",file = log_file)
                                break
                    except:
                        host = Linux(ipaddr[0], ipaddr[1], ipaddr[2])
                        print("错误的话会经过这里",file = log_file)
                        localpath = r'/home/dar/uft_download/uft_so/' + so
                        if ipaddr[1] == "combine_mauft":
                            serverpath = r'/home/combine_mauft/appcom/' + so
                        else:
                            serverpath = r'/home/secumauft/appcom/' + so
                        now = datetime.datetime.now().strftime("%Y-%m-%d/%H:%M:%S")
                        if flag == 0:
                            if ipaddr[1] == "combine_mauft":
                                stdin, stdout, stderr = ssh.exec_command(
                                    "cp -p /home/combine_mauft/appcom/{0} /home/combine_mauft/appcom/{1}".format(
                                        so, so + now))
                            else:
                                stdin, stdout, stderr = ssh.exec_command(
                                    "cp -p /home/secumauft/appcom/{0} /home/secumauft/appcom/{1}".format(so,
                                                                                                         so + now))
                        host.sftp_put(localpath, serverpath)

if __name__ == "__main__":
    while True:
        conn = pymysql.connect(host='10.20.27.20', user='root', passwd='Dar960207!@#', db="dar")
        # 连接数据库
        cur = conn.cursor()
        sql_1 = "select id,output,up_version,en_product,up_host,update_way,begin_date,up_persion from updateturn where up_status = 1 order by id asc limit 1"

        num = cur.execute(sql_1)  # 执行查询语句并接受返回结果的数量
        data = cur.fetchall()  # 获取所有的查询结果，以元祖的形式
        try:
            if num == 1 and data[0][4] == "UFT":
                now = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
                log_file = open(r"./uft_log/{0}{1}".format(data[0][7],now), "w", encoding='utf-8')
                m_time = datetime.datetime.now().strftime("%H%M%S") #获取当前时间，并进行格式化
                print("开始升级了",file = log_file)
                start = time.time() # 获取时间戳。
                print("开始清空文件夹",file = log_file)
                clear_dir() # 清空文件夹的内容
                print("清空文件夹完成",file = log_file)
                print("下载集成包",file = log_file)
                down_info = integrated_package_download(g_product = data[0][3],output = data[0][1],g_version = data[0][2])
                print("下载集成包完成",file = log_file)
                sql_2 = 'update updateturn set progress = "30 下载完成，正在解压" where id = "{}"'.format(data[0][0])
                num2 = cur.execute(sql_2)
                conn.commit()
                print('进行解压压缩包',file = log_file)
                rar_file(down_info)
                print("解压压缩包完成",file = log_file)
                sql_3 = 'update updateturn set progress = "50，解压完成，正在上传so文件" where id = {}'.format(data[0][0])
                end = time.time()
                now_time = datetime.datetime.now().strftime('%H:%M:%S')
                print("现在开始上传文件",file = log_file)
                uft_upload()
                print("上传文件完成",file = log_file)
                sql_4 = 'update updateturn set up_status = 2,use_time="{0}" where id = "{1}"'.format(end - start,data[0][0])
                sql_5 = 'update updateturn set progress = "100,升级完成" where id = "{}"'.format(data[0][0])
                cur.execute(sql_3)
                cur.execute(sql_4)
                cur.execute(sql_5)
                conn.commit()
        except:
            sql_6 = 'update updateturn set up_status = 2 where  id = "{}"'.format(data[0][0])
            num5 = cur.execute(sql_6)
            conn.commit()
        print("结束了")
        cur.close()
        conn.close()
        time.sleep(5)









